package com.zmj.demo.service.impl;

import com.zmj.demo.mapper.HelloMapper;
import com.zmj.demo.pojo.entity.Hello;
import com.zmj.demo.service.HelloService;
import com.zmj.framework.base.service.impl.BaseServiceImpl;
import com.zmj.framework.circuitBreaker.CircuitBreakerUtil;
import com.zmj.framework.exception.business.BizException;
import com.zmj.framework.response.Result;
import io.github.resilience4j.bulkhead.BulkheadFullException;
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class HelloServiceImpl extends BaseServiceImpl<HelloMapper, Hello> implements HelloService {
    @Autowired
    private CircuitBreakerRegistry circuitBreakerRegistry;
    //请求计数器
    private static AtomicInteger count = new AtomicInteger(0);

    @Override
    public Result testTimeOut() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Result.success("finnish");
    }

    @Override
    public Result testCircuitBreaker() throws Exception {
        return doProcess();
    }

    @Override
    @CircuitBreaker(name = "simple", fallbackMethod = "fallBack")
    @Retry(name = "simple", fallbackMethod = "fallBack")
    @RateLimiter(name = "simple", fallbackMethod = "fallback")
    public Result testCircuitBreakerAop() throws TimeoutException, InterruptedException {
        return doProcess();
    }


    private Result fallBack(Throwable throwable){
        log.info(throwable.getLocalizedMessage() + ",方法被降级了~~");
        CircuitBreakerUtil.getCircuitBreakerStatus("降级方法中:", circuitBreakerRegistry.circuitBreaker("simple"));
        return Result.fail("方法被降级了");
    }

    private Result fallBack(CallNotPermittedException e){
        log.info("熔断器已经打开，拒绝访问被保护方法~");
        CircuitBreakerUtil.getCircuitBreakerStatus("熔断器打开中:", circuitBreakerRegistry.circuitBreaker("simple"));
        return Result.fail("熔断器已经打开，拒绝访问被保护方法");
    }

    @RateLimiter(name = "simple", fallbackMethod = "fallback")
    public Result testRateLimiterAop() throws TimeoutException, InterruptedException {
        return doProcess();
    }

    private Result fallback(BulkheadFullException e){
        log.info("服务失败: " + e.getLocalizedMessage());
        return Result.fail("令牌桶熔断");
    }

    private Result doProcess() throws InterruptedException {
        int num = count.getAndIncrement();
        log.info("count的值 = " + num);
        if (num % 4 == 1){
            throw new BizException("模拟异常");
        }
        return Result.success("ok");
    }

    public static String doPost(Map<String, String> map, String charset) {
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        String result = null;
        try {
            CookieStore cookieStore = new BasicCookieStore();
            httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
            httpPost = new HttpPost("http://localhost:8080/testtoolmanagement/LoginServlet");
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
                list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
            }
            if (list.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
                httpPost.setEntity(entity);
            }
            httpClient.execute(httpPost);
            String JSESSIONID = null;
            String cookie_user = null;
            List<Cookie> cookies = cookieStore.getCookies();
            for (int i = 0; i < cookies.size(); i++) {
                if (cookies.get(i).getName().equals("JSESSIONID")) {
                    JSESSIONID = cookies.get(i).getValue();
                }
                if (cookies.get(i).getName().equals("cookie_user")) {
                    cookie_user = cookies.get(i).getValue();
                }
            }
            if (cookie_user != null) {
                result = JSESSIONID;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }
}
